{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3d0d50a2",
   "metadata": {},
   "source": [
    "# DAY 29"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8fd27ee0",
   "metadata": {},
   "source": [
    "到此为止，训练营已经完成接近一半的任务，如果你扎实的跟完前28天的作业，你的能力已经是相当优秀。\n",
    "\n",
    "既然函数可以复用，有了类和装饰器，那么类还能进一步封装么？可以的，类也有装饰器\n",
    "\n",
    "回顾一下，函数的装饰器是 ：接收一个函数，返回一个修改后的函数。我们之前是用复用的思想来看装饰器的，换一个角度理解，当你想修改一个函数的时候，可以通过装饰器方法来修改而无需重新定义这个函数。\n",
    "\n",
    "类也有修饰器，他的逻辑类似：接收一个类，返回一个修改后的类。例如\n",
    "1. 添加新的方法或属性（如示例中的 log 方法）。\n",
    "2. 修改原有方法（如替换 __init__ 方法，添加日志）。\n",
    "3. 甚至可以返回一个全新的类（继承或组合原类）。\n",
    "\n",
    "通过类装饰器，可以在不修改类内部代码的情况下，为多个类统一添加功能（如日志、统计）\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28e277cb",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    " **类装饰器 vs 函数装饰器：核心区别**\n",
    "| **特性**         | **函数装饰器**                                | **类装饰器**                                |\n",
    "|------------------|---------------------------------------------|---------------------------------------------|\n",
    "| **作用对象**     | 函数（function）                              | 类（class）                                 |\n",
    "| **传入参数**     | 接收函数作为参数（`def decorator(func):`）    | 接收类作为参数（`def decorator(cls):`）      |\n",
    "| **返回值**       | 返回**包装后的函数**（通常是闭包）            | 返回**修改后的类**（可以是原类或新类）      |\n",
    "| **常见用途**     | 修改函数行为（如日志、计时、权限验证）        | 修改类的结构（如添加属性、方法、修改初始化逻辑） |\n",
    "| **核心逻辑**     | 用闭包包裹函数，在不修改函数代码的前提下扩展功能 | 直接修改类的定义（如添加/替换方法、属性）    |\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ee767e61",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[LOG] 实例化对象: SimplePrinter\n",
      "Alice: Hello, World!\n",
      "[LOG] 这是装饰器添加的日志方法\n"
     ]
    }
   ],
   "source": [
    "# 定义类装饰器：为类添加日志功能\n",
    "def class_logger(cls):\n",
    "    # 保存原始的 __init__ 方法\n",
    "    original_init = cls.__init__\n",
    "\n",
    "    def new_init(self, *args, **kwargs):\n",
    "        # 新增实例化日志\n",
    "        print(f\"[LOG] 实例化对象: {cls.__name__}\")\n",
    "        original_init(self, *args, **kwargs)  # 调用原始构造方法\n",
    "\n",
    "    # 将类的 __init__ 方法替换为新方法\n",
    "    cls.__init__ = new_init\n",
    "\n",
    "    # 为类添加一个日志方法（示例）\n",
    "    def log_message(self, message):\n",
    "        print(f\"[LOG] {message}\")\n",
    "\n",
    "    cls.log = log_message  # 将方法绑定到类，这是一种将外部函数添加为类的属性的方法\n",
    "    return cls\n",
    "\n",
    "\n",
    "# 定义简单打印类，应用装饰器\n",
    "# 同样是语法糖的写法\n",
    "@class_logger\n",
    "class SimplePrinter:\n",
    "    def __init__(self, name):\n",
    "        self.name = name  # 构造方法：初始化名称\n",
    "\n",
    "    def print_text(self, text):\n",
    "        \"\"\"简单打印方法\"\"\"\n",
    "        print(f\"{self.name}: {text}\")\n",
    "\n",
    "\n",
    "# 使用示例\n",
    "printer = SimplePrinter(\"Alice\")  # 实例化时触发装饰器的日志\n",
    "printer.print_text(\"Hello, World!\")  # 调用普通方法\n",
    "printer.log(\"这是装饰器添加的日志方法\")  # 调用装饰器新增的方法"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b58d0c0d",
   "metadata": {},
   "source": [
    "注意到其中的cls.log = log_message 这行代码，他把外部的函数赋值给了类的新定义的属性，这里我们介绍这种写法\n",
    "\n",
    "实际上，定义类的方法，有2类写法\n",
    "1. 在类定义内部直接写方法，这是静态方法，一般定义类都这么完成。\n",
    "2. 在类定义外部定义方法，然后把方法赋值给类的属性---这是一种动态方法，常在装饰器中使用，可以再外部修改类的方法。\n",
    "\n",
    " **本质区别**\n",
    "| **特性**         | **类内部定义方法**               | **外部赋值定义方法**               |\n",
    "|------------------|----------------------------------|------------------------------------|\n",
    "| **语法**         | 在 `class` 块内使用 `def`        | 定义函数后赋值给类属性（如 `cls.fn = fn`） |\n",
    "| **作用域**       | 方法可以直接访问类的其他私有成员 | 需要通过 `self` 或类名显式访问     |\n",
    "| **动态性**       | 类定义后方法固定                 | 可以在运行时动态添加/修改方法     |\n",
    "| **常见场景**     | 常规类定义                       | 装饰器、元类、动态编程             |\n",
    "\n",
    "\n",
    "两种方式的本质都是将函数对象绑定到类的属性上，只是语法和应用场景不同。装饰器中常用外部赋值，是为了在不修改原类代码的情况下增强类的功能。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d291a287",
   "metadata": {},
   "source": [
    "ps：之前无论是函数还是类的装饰器，我们都发现是先有装饰器，再有类。那既然我们说了装饰器除了让原本的代码更加清晰可读可复用，还具有修改函数or类的功能。那如何修改之前已经写好的类or函数呢？\n",
    "\n",
    "所以你还是需要理解 装饰器本质就是一个语法糖，对类而言：@decorator 语法只是 MyClass = decorator(MyClass) 的简写，即使类已定义，仍可手动调用装饰器函数修改它。\n",
    "\n",
    "总结：装饰器的核心是动态修改类 / 函数，而不改变原代码。通过外部赋值，可以在不修改类定义的前提下，为类添加新方法或修改已有方法。---理解动态的含义\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "vs",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
